package com.xb.loan.cashier.biz.pay.unionpay.config;

import com.xb.loan.cashier.biz.pay.unionpay.UnionPayConstants;
import com.xb.loan.cashier.biz.pay.unionpay.util.UnionPayUtil;
import com.xb.loan.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Properties;

/**
 * 银联软件开发工具包 配制
 */
public class UnionPayConfig {
    
    private static Logger log = LoggerFactory.getLogger(UnionPayConfig.class);

	public static final String FILE_NAME = "config/unionpay_config.properties";
	
    public UnionPayConfig() {
        super();
    }
	
	/** 签名证书路径. */
	private String signCertPath;
	/** 签名证书密码. */
	private String signCertPwd;
	/** 签名证书类型. */
	private String signCertType;
	/** 加密公钥证书路径. */
	private String encryptCertPath;
	/** 验证签名公钥证书目录. */
	private String validateCertDir;
	/** 磁道加密证书路径. */
	private String encryptTrackCertPath;
	/** 磁道加密公钥模数. */
	private String encryptTrackKeyModulus;
	/** 磁道加密公钥指数. */
	private String encryptTrackKeyExponent;
	/** 证书使用模式(单证书/多证书) */
	private String singleMode;

	
	/** 配置文件中签名证书路径常量. */
	public static final String SIGNCERT_PATH = "unionpay.signCert.path";
	/** 配置文件中签名证书密码常量. */
	public static final String SIGNCERT_PWD = "unionpay.signCert.pwd";
	/** 配置文件中签名证书类型常量. */
	public static final String SIGNCERT_TYPE = "unionpay.signCert.type";
	/** 配置文件中密码加密证书路径常量. */
	public static final String ENCRYPTCERT_PATH = "unionpay.encryptCert.path";
	/** 配置文件中磁道加密证书路径常量. */
	public static final String ENCRYPTTRACKCERT_PATH = "unionpay.encryptTrackCert.path";
	/** 配置文件中磁道加密公钥模数常量. */
	public static final String ENCRYPTTRACKKEY_MODULUS = "unionpay.encryptTrackKey.modulus";
	/** 配置文件中磁道加密公钥指数常量. */
	public static final String ENCRYPTTRACKKEY_EXPONENT = "unionpay.encryptTrackKey.exponent";
	/** 配置文件中验证签名证书目录常量. */
	public static final String VALIDATECERT_DIR = "unionpay.validateCert.dir";

	/** 配置文件中证书使用模式 */
	public static final String SINGLEMODE = "unionpay.singleMode";
	/** 操作对象. */
	private static UnionPayConfig config;
	/** 属性文件对象. */
	private Properties properties;


	/**
	 * 获取config对象.
	 * 
	 * @return
	 */
	public static UnionPayConfig getConfig() {
		if (null == config) {
			config = new UnionPayConfig();
			config.loadPropertiesFromSrc();
		}
		return config;
	}

	/**
	 * 从properties文件加载
	 * 
	 * @param rootPath
	 *            不包含文件名的目录.
	 */
	public void loadPropertiesFromPath(String rootPath) {
		if (StringUtils.isNotBlank(rootPath)) {
			File file = new File(rootPath + File.separator + FILE_NAME);
			InputStream in = null;
			if (file.exists()) {
				try {
					in = new FileInputStream(file);
					BufferedReader bf = new BufferedReader(
							new InputStreamReader(in, "utf-8"));
					properties = new Properties();
					properties.load(bf);
					loadProperties(properties);
				} catch (FileNotFoundException e) {
					log.error(e.getMessage(), e);
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				} finally {
					if (null != in) {
						try {
							in.close();
						} catch (IOException e) {
							log.error(e.getMessage(), e);
						}
					}
				}
			} else {
				// 由于此时可能还没有完成LOG的加载，因此采用标准输出来打印日志信息
				//System.out.println(rootPath + FILE_NAME + "不存在,加载参数失败");
			}
		} else {
			loadPropertiesFromSrc();
		}

	}

	/**
	 * 从classpath路径下加载配置参数
	 */
	public void loadPropertiesFromSrc() {
		InputStream in = null;
		try {
			// Properties pro = null;
			log.debug("从classpath: " +UnionPayConfig.class.getClassLoader().getResource("").getPath()+" 获取属性文件"+FILE_NAME);
			in = UnionPayConfig.class.getClassLoader()
					.getResourceAsStream(FILE_NAME);
			if (null != in) {
				BufferedReader bf = new BufferedReader(new InputStreamReader(
						in, "utf-8"));
				properties = new Properties();
				try {
					properties.load(bf);
				} catch (IOException e) {
					throw e;
				}
			} else {
				log.error(FILE_NAME + "属性文件未能在classpath指定的目录下 "+UnionPayConfig.class.getClassLoader().getResource("").getPath()+" 找到!");
				return;
			}
			loadProperties(properties);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		} finally {
			if (null != in) {
				try {
					in.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
		}
	}

	/**
	 * 根据传入的 {@link #load(java.util.Properties)}对象设置配置参数
	 * 
	 * @param pro
	 */
	public void loadProperties(Properties pro) {
		log.debug("开始从属性文件中加载配置项");
		String value = null;
		value = pro.getProperty(SINGLEMODE);
		if (UnionPayUtil.isEmpty(value) || UnionPayConstants.TRUE_STRING.equals(value)) {
			this.singleMode = UnionPayConstants.TRUE_STRING;
			log.debug("单证书模式，使用配置文件配置的私钥签名证书，SingleCertMode:[" + this.singleMode + "]");
			// 单证书模式
			value = pro.getProperty(SIGNCERT_PATH);
			
			if (!UnionPayUtil.isEmpty(value)) {
				this.signCertPath = value.trim();
				log.debug("配置项：私钥签名证书路径==>"+SIGNCERT_PATH +"==>"+ value+" 已加载");
			}
			value = pro.getProperty(SIGNCERT_PWD);
			if (!UnionPayUtil.isEmpty(value)) {
				this.signCertPwd = value.trim();
				log.debug("配置项：私钥签名证书密码==>"+SIGNCERT_PWD +" 已加载");
			}
			value = pro.getProperty(SIGNCERT_TYPE);
			if (!UnionPayUtil.isEmpty(value)) {
				this.signCertType = value.trim();
				log.debug("配置项：私钥签名证书类型==>"+SIGNCERT_TYPE +"==>"+ value+" 已加载");
			}
		} else {
			// 多证书模式
			this.singleMode = UnionPayConstants.FALSE_STRING;
			log.debug("多证书模式，不需要加载配置文件中配置的私钥签名证书，SingleMode:[" + this.singleMode + "]");
		}
		value = pro.getProperty(ENCRYPTCERT_PATH);
		if (!UnionPayUtil.isEmpty(value)) {
			this.encryptCertPath = value.trim();
			log.debug("配置项：敏感信息加密证书==>"+ENCRYPTCERT_PATH +"==>"+ value+" 已加载");
		}
		value = pro.getProperty(VALIDATECERT_DIR);
		if (!UnionPayUtil.isEmpty(value)) {
			this.validateCertDir = value.trim();
			log.debug("配置项：验证签名证书路径(这里配置的是目录，不要指定到公钥文件)==>"+VALIDATECERT_DIR +"==>"+ value+" 已加载");
		}
		value = pro.getProperty(ENCRYPTTRACKCERT_PATH);
		if (!UnionPayUtil.isEmpty(value)) {
			this.encryptTrackCertPath = value.trim();
		}
		
		value = pro.getProperty(ENCRYPTTRACKKEY_EXPONENT);
		if (!UnionPayUtil.isEmpty(value)) {
			this.encryptTrackKeyExponent = value.trim();
		}

		value = pro.getProperty(ENCRYPTTRACKKEY_MODULUS);
		if (!UnionPayUtil.isEmpty(value)) {
			this.encryptTrackKeyModulus = value.trim();
		}
	}

	public String getSignCertPath() {
		return signCertPath;
	}

	public void setSignCertPath(String signCertPath) {
		this.signCertPath = signCertPath;
	}

	public String getSignCertPwd() {
		return signCertPwd;
	}

	public void setSignCertPwd(String signCertPwd) {
		this.signCertPwd = signCertPwd;
	}

	public String getSignCertType() {
		return signCertType;
	}

	public void setSignCertType(String signCertType) {
		this.signCertType = signCertType;
	}

	public String getEncryptCertPath() {
		return encryptCertPath;
	}

	public void setEncryptCertPath(String encryptCertPath) {
		this.encryptCertPath = encryptCertPath;
	}
	
	public String getValidateCertDir() {
		return validateCertDir;
	}

	public void setValidateCertDir(String validateCertDir) {
		this.validateCertDir = validateCertDir;
	}

	public Properties getProperties() {
		return properties;
	}

	public void setProperties(Properties properties) {
		this.properties = properties;
	}

	public String getEncryptTrackCertPath() {
		return encryptTrackCertPath;
	}

	public void setEncryptTrackCertPath(String encryptTrackCertPath) {
		this.encryptTrackCertPath = encryptTrackCertPath;
	}
	
	public String getSingleMode() {
		return singleMode;
	}

	public void setSingleMode(String singleMode) {
		this.singleMode = singleMode;
	}

	public String getEncryptTrackKeyExponent() {
		return encryptTrackKeyExponent;
	}

	public void setEncryptTrackKeyExponent(String encryptTrackKeyExponent) {
		this.encryptTrackKeyExponent = encryptTrackKeyExponent;
	}

	public String getEncryptTrackKeyModulus() {
		return encryptTrackKeyModulus;
	}

	public void setEncryptTrackKeyModulus(String encryptTrackKeyModulus) {
		this.encryptTrackKeyModulus = encryptTrackKeyModulus;
	}
}
